/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package team11;

/**
 * 文件操作工具类 提供数据文件加载、结果保存和模型信息保存功能
 *
 * @author 朱婧雯
 */
import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class FileUtil {

    /**
     * 增强的文件加载方法，支持更多配置
     *
     * @param folderPath
     * @param fileExtensions
     * @return
     */
    public static double[][] loadTestData(String folderPath, String... fileExtensions) {
        File folder = new File(folderPath);

        if (!folder.exists() || !folder.isDirectory()) {
            System.out.println("测试文件夹不存在: " + folderPath);
            return null;
        }

        File[] files = folder.listFiles();
        if (files == null || files.length == 0) {
            System.out.println("测试文件夹为空: " + folderPath);
            return null;
        }

        String[] extensions = fileExtensions.length > 0 ? fileExtensions
                : new String[]{".txt", ".csv", ".data", ".dat"};

        List<double[]> dataList = new ArrayList<>();
        int totalFiles = 0;

        for (File file : files) {
            if (file.isFile() && hasValidExtension(file.getName(), extensions)) {
                System.out.println("读取测试文件: " + file.getName());
                List<double[]> fileData = readDataFile(file);
                dataList.addAll(fileData);
                totalFiles++;
            }
        }

        if (dataList.isEmpty()) {
            System.out.println("未找到有效的测试数据文件");
            return null;
        }

        System.out.printf("成功从 %d 个文件加载 %d 个测试样本%n", totalFiles, dataList.size());
        return dataList.toArray(new double[0][]);
    }

    /**
     * 检查文件扩展名是否有效
     */
    private static boolean hasValidExtension(String fileName, String[] extensions) {
        String lowerName = fileName.toLowerCase();
        for (String ext : extensions) {
            if (lowerName.endsWith(ext.toLowerCase())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 增强的数据读取方法，支持错误恢复和进度显示
     */
    private static List<double[]> readDataFile(File file) {
        List<double[]> dataList = new ArrayList<>();
        int lineCount = 0;
        int errorCount = 0;

        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = reader.readLine()) != null) {
                lineCount++;
                line = line.trim();

                if (line.isEmpty() || line.startsWith("#") || line.startsWith("//")) {
                    continue;
                }

                try {
                    double[] data = parseDataLine(line);
                    if (data != null) {
                        dataList.add(data);
                    }
                } catch (NumberFormatException e) {
                    errorCount++;
                    if (errorCount <= 5) { // 只显示前5个错误
                        System.out.printf("文件 %s 第 %d 行数据格式错误: %s%n",
                                file.getName(), lineCount, line);
                    }
                }
            }

            if (errorCount > 5) {
                System.out.printf("... 还有 %d 个错误未显示%n", errorCount - 5);
            }

        } catch (IOException e) {
            System.err.println("读取文件失败: " + file.getName() + " - " + e.getMessage());
        }

        System.out.printf("文件 %s: 读取 %d 行，成功 %d 条，错误 %d 条%n",
                file.getName(), lineCount, dataList.size(), errorCount);

        return dataList;
    }

    /**
     * 解析数据行，支持多种格式
     */
    private static double[] parseDataLine(String line) {
        // 支持逗号、空格、制表符、分号分隔
        String[] parts = line.split("[, \t;]+");
        if (parts.length >= 2) {
            double x = Double.parseDouble(parts[0]);
            double y = Double.parseDouble(parts[1]);
            return new double[]{x, y};
        }
        return null;
    }

    /**
     * 增强的结果保存方法
     *
     * @param inputs
     * @param predictions
     * @param actuals
     * @param filePath
     */
    public static void savePredictions(double[][] inputs, double[] predictions,
            double[] actuals, String filePath) {
        try (PrintWriter writer = new PrintWriter(new FileWriter(filePath))) {
            writer.println("# 测试结果");
            writer.println("# 输入X, 输入Y, 预测值, 真实值, 绝对误差, 相对误差(%)");

            double totalError = 0;
            int count = 0;

            for (int i = 0; i < inputs.length; i++) {
                double error = Math.abs(predictions[i] - actuals[i]);
                double relativeError = actuals[i] != 0 ? (error / Math.abs(actuals[i])) * 100 : 0;
                totalError += error;
                count++;

                writer.printf("%.6f, %.6f, %.6f, %.6f, %.6f, %.2f%%%n",
                        inputs[i][0], inputs[i][1],
                        predictions[i], actuals[i], error, relativeError);
            }

            double mae = totalError / count;
            writer.println();
            writer.printf("# 统计信息: 样本数=%d, 平均绝对误差=%.6f", count, mae);

            System.out.println("测试结果已保存到: " + filePath);
            System.out.printf("统计信息: 样本数=%d, 平均绝对误差=%.6f%n", count, mae);

        } catch (IOException e) {
            System.err.println("保存测试结果失败: " + e.getMessage());
        }
    }

    /**
     * 保存模型配置信息
     *
     * @param filePath
     * @param modelInfo
     */
    public static void saveModelInfo(String filePath, String modelInfo) {
        try (PrintWriter writer = new PrintWriter(new FileWriter(filePath))) {
            writer.println("# 模型配置信息");
            writer.println(modelInfo);
            System.out.println("模型配置已保存到: " + filePath);
        } catch (IOException e) {
            System.err.println("保存模型配置失败: " + e.getMessage());
        }
    }
}
